package com.jh.user.business.impl;

import cn.jh.common.exception.ServiceException;
import cn.jh.common.utils.CommonConstants;
import cn.jh.common.utils.CommonsUtil;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Lists;
import com.google.common.collect.Table;
import com.jh.user.business.ChannelRateBusiness;
import com.jh.user.business.UserBusiness;
import com.jh.user.pojo.BrandRate;
import com.jh.user.pojo.ChannelRate;
import com.jh.user.pojo.ThirdLevelDistribution;
import com.jh.user.pojo.User;
import com.jh.user.pojo.enums.UserGrade;
import com.jh.user.pojo.freeQuick.PassageWayRegister;
import com.jh.user.pojo.freeQuick.PassagewayBankInfo;
import com.jh.user.repository.*;
import com.jh.user.repository.freeQuick.PassageWayRegisterRepository;
import com.jh.user.service.freeQuick.FreeQuickService;
import com.jh.user.util.Commons;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

@Service
public class UserBusinessImpl implements UserBusiness {

    @Autowired
    private UserRepository userRepository;
    @Autowired
    private ChannelRateBusiness channelRateBusiness;
    @Autowired
    private ChannelRateRepository channelRateRepository;
    @Autowired
    private BrandRateRepository brandRateRepository;
    @Autowired
    private ThirdLevelDistributionRepository thirdLevelDistributionRepository;
    @Autowired
    private EntityManager entityManager;
    @Autowired
    private FreeQuickService freeQuickService;
    @Autowired
    private PassageWayRegisterRepository passageWayRegisterRepository;
    @Autowired
    private PassagewayBankinfoRepository passagewayBankinfoRepository;

    @Override
    public User findUserById(long userId) {
        return userRepository.findUserById(userId);
    }

    @Override
    @Transactional
    public void updateShopStatus(User user) {
        userRepository.updateShopStatus(user.getShopsStatus(), user.getId());
    }

    @Override
    public User getByPhone(String phone) {
        return userRepository.getByPhone(phone);
    }

    @Override
    public int findUserListByPreUserId(long userId) {
        return userRepository.countByPreUserId(userId);
    }

    @Transactional
    @Override
    public User upGrade(long userId, UserGrade grade) throws ServiceException {
        User user = userRepository.findUserById(userId);
        if (user == null) {
            throw new ServiceException("用户信息不存在");
        }
        if (!user.isIdentity()) {
            throw new ServiceException("对不起，您还未通过实名认证！");
        }
        UserGrade userGrade = UserGrade.of(Integer.valueOf(user.getGrade()));
        if (userGrade == null) {
            throw new ServiceException("用户等级有误");
        }
        if (grade.getValue() <= userGrade.getValue()) {
            throw new ServiceException("提升等级必须高于您当前等级");
        }
        // 被推荐并实名认证通过的用户数
        int recCount = userRepository.countByPreUserId(userId);
        if (recCount == 0) {
            throw new ServiceException("推荐用户数不满足升级的条件");
        }
        // 根据贴牌id和推荐的有效人数查询满足条件的信息
        List<ThirdLevelDistribution> tldList = thirdLevelDistributionRepository.findThirdLevelDistribution(user.getBrandId(), recCount);
        // 可升的最高级别
        Integer maxUpGradeLevel = tldList.size();
        if (grade.getValue() > maxUpGradeLevel.shortValue()) {
            if (userGrade.getValue() == maxUpGradeLevel.shortValue()) {
                throw new ServiceException("您暂时未满足升级所需的条件");
            }
            throw new ServiceException("您当前可升的最高等级为" + UserGrade.of(maxUpGradeLevel).getDesc());
        }
        user.setGrade(String.valueOf(grade.getValue()));
        userRepository.saveAndFlush(user);

        // 查询指定等级的公共费率信息
        List<BrandRate> brandRateList = brandRateRepository.findBrandRate(user.getBrandId(), grade);
        if (brandRateList == null || brandRateList.isEmpty()) {
            throw new ServiceException("等级");
        }
        // 查询用户通道费率
        List<ChannelRate> channelRateList = channelRateRepository.findByUserId(userId);
        Table<Long, Short, ChannelRate> table = HashBasedTable.create();
        for (ChannelRate rate : channelRateList) {
            table.put(rate.getChannelId(), rate.getPayType(), rate);
        }
        List<ChannelRate> updateList = Lists.newArrayList();
        for (BrandRate rate: brandRateList) {
            ChannelRate channelRate = table.get(rate.getChannelId(), rate.getPayType());
            ChannelRate cr = new ChannelRate();
            if (channelRate == null) { // 初始化
                channelRate = ChannelRate.initRate(user, rate);
            } else { // 更新
                cr = channelRate;
                channelRate.update(rate);
            }
            updateList.add(channelRate);
            upGradeToModifyMerchantFeeInfo(cr, channelRate);
        }
        if (!updateList.isEmpty()) {
            channelRateRepository.save(updateList);
        }
        return user;
    }

    /**
     * 等级升级/个人费率修改时，更新上游个人通道费率信息
     * @param oldCr 修改前的个人费率信息
     * @param channelRate 修改后的个人费率信息
     * @throws ServiceException
     */
    public void upGradeToModifyMerchantFeeInfo(ChannelRate oldCr, ChannelRate channelRate) throws ServiceException {
        long userId = channelRate.getUserId();
        long channelId = channelRate.getChannelId();
        BigDecimal rate = channelRate.getRate();
        BigDecimal extraFee = channelRate.getExtraFee();

        /* 1、根据userId和channelId获取用户通道注册信息 */
        PassageWayRegister passageWayRegister = passageWayRegisterRepository.findByUserIdAndChannelProductCode(String.valueOf(userId), String.valueOf(channelId));
        if (null == passageWayRegister) {
            throw new ServiceException("用户还未注册通道信息！");
        }
        String requestNo = passageWayRegister.getRequestNo();
        String channelMerchantNo = passageWayRegister.getChannelMerchantNo();

        /* 2、根据channelMerchantNo获取通道绑定银行卡信息 */
        List<PassagewayBankInfo> passagewayBankInfoList = passagewayBankinfoRepository.findByMerchantNoAndChannelProductCode(channelMerchantNo, String.valueOf(channelId));
        if (null == passagewayBankInfoList || passagewayBankInfoList.size() == 0) {
            throw new ServiceException("通道还未绑定用户银行卡信息！");
        }
        for (PassagewayBankInfo passagewayBankInfo : passagewayBankInfoList) {
            String cardType = passagewayBankInfo.getCardType();
            if (null != oldCr) {
                BigDecimal oldCrRate = oldCr.getRate();
                BigDecimal oldCrExtraFee = oldCr.getExtraFee();
                if (null == oldCrRate) {
                    oldCrRate = new BigDecimal("0.0000");
                }
                if (null == oldCrExtraFee) {
                    oldCrExtraFee = new BigDecimal("0");
                }
                if (rate.compareTo(oldCrRate) != 0) {
                    // 费率被修改
                    Boolean result = modifyChannelRate(channelId, String.valueOf(rate), requestNo, channelMerchantNo, CommonConstants.BIZ_TYPE_01, cardType);
                    if (result) {
                        // 修改成功
                    }
                }
                if (extraFee.compareTo(oldCrExtraFee) != 0) {
                    int fee = extraFee.intValue();
                    // 单笔提现费被修改
                    Boolean result = modifyChannelRate(channelId, String.valueOf(fee), requestNo, channelMerchantNo, CommonConstants.BIZ_TYPE_03, cardType);
                    if (result) {
                        // 修改成功
                    }
                }
            }
        }
    }

    /**
     * 修改费率
     * @param channelId 通道产品编码
     * @param rate      费率/提现额外费用
     * @param requestNo 流水号
     * @param channelMerchantNo 通道商户号
     * @param bizType   费类型
     * @param cardType  卡类型
     * @return
     * @throws ServiceException
     */
    public Boolean modifyChannelRate(long channelId, String rate, String requestNo, String channelMerchantNo, String bizType, String cardType) throws ServiceException {
        Boolean resFlag = false;
        if (CommonConstants.CREDIT_CARD.equals(cardType)) {
            cardType = CommonConstants.CREDIT_0;
        }
        if (CommonConstants.DEBIT_CARD.equals(cardType)) {
            cardType = CommonConstants.DEBIT_2;
        }
        Map<String, Object> resMap = freeQuickService.modifyMerchantFeeInfo(requestNo, channelMerchantNo, String.valueOf(channelId), cardType, bizType, rate);
        if (null != resMap) {
            JSONObject jsonObject = JSONObject.fromObject(resMap);
            String bizCode = jsonObject.getString("bizCode");
            String code = jsonObject.getString("code");
            if ("1".equals(bizCode) && "200".equals(code)) {
                //成功
                resFlag = true;
            } else {
                String quickError = CommonsUtil.freeQuickError(bizCode);
                throw new ServiceException("修改上游个人通道费率失败，" + quickError + "！");
            }
        }
        return resFlag;
    }
}
